package com.yaodian100.ec.creditcard.web;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.service.DomainService;
import com.yaodian100.core.common.utils.DateUtil;
import com.yaodian100.core.menu.entity.Menu;
import com.yaodian100.ec.category.entity.Category;
import com.yaodian100.ec.category.service.CategoryService;
import com.yaodian100.ec.common.EcConstant;
import com.yaodian100.ec.common.web.AbstractAction;
import com.yaodian100.ec.creditcard.entity.CardDetail;
import com.yaodian100.ec.creditcard.entity.Creditcard;
import com.yaodian100.ec.creditcard.entity.Creditcard.Range;
import com.yaodian100.ec.creditcard.entity.CreditcardDetail;
import com.yaodian100.ec.creditcard.entity.CreditcardSetting;
import com.yaodian100.ec.creditcard.service.CreditcardDetailService;
import com.yaodian100.ec.creditcard.service.CreditcardService;
import com.yaodian100.ec.creditcard.service.CreditcardSettingService;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.service.ProductService;

public class CreditcardAction extends AbstractAction {
	
	private final Logger logger = LoggerFactory.getLogger(CreditcardAction.class);
	@Autowired
	private CreditcardService creditcardService;
	@Autowired
	private CreditcardDetailService creditcardDetailService;
	@Autowired
	private CreditcardSettingService creditcardSettingService;
	@Autowired
	private CategoryService categoryService;
	@Autowired
	private ProductService productService;
	@Autowired
	private DomainService<Menu> menuService;
	
	/* 搜寻条件 */
	private List<Creditcard.Range> paramRanges = Arrays.asList(Creditcard.Range.Order, Creditcard.Range.Category, Creditcard.Range.Product);
	private String paramName;
	private Date paramStartDate;
	private Date paramEndDate;
	private String paramCookie;
	private String paramDomain;
	private String[] paramEnable = new String[] { "true", "false" };
	
	/* 选单 */
	private List<Creditcard.Range> menuRange = Arrays.asList(Creditcard.Range.Order, Creditcard.Range.Category, Creditcard.Range.Product);
	private Menu menuDomain;
	private Menu menuChannel;
	private Map<String, CreditcardSetting> menuSetting;
	
	/* 表单 */
	private String creditcardId;
	private Creditcard creditcard;
	private String startDate;
	private String startTime;
	private String endDate;
	private String endTime;
	private boolean ignoreCookie;
	private int operation;
	private String bankId;
	private String bankIdNote;
	private List<CardDetail> showDetails;
	private List<CreditcardDetail> cardDetails;
	
	/* 列表 */
	private List<Creditcard> campaignList;
	
	public String list() {
		return "list";
	}
	
	public String search() {
		try {
			CommonCriteria cri = new CommonCriteria();
			if (StringUtils.isNotBlank(paramName)) {
				cri.addRlike("campaignName", paramName);
			}
			if (paramStartDate != null) {
				cri.addGe("endDate", DateUtil.getFirstTimestamp(Calendar.DATE, paramStartDate));
			}
			if (paramEndDate != null) {
				cri.addLe("startDate", DateUtil.getLastTimestamp(Calendar.DATE, paramEndDate));
			}
			if (paramRanges != null && paramRanges.size() > 0) {
				cri.addIn("range", paramRanges);
			}
			if (StringUtils.isNotBlank(paramCookie)) {
				cri.addEq("cookie", paramCookie);
			}
			if (StringUtils.isNotBlank(paramDomain)) {
				cri.addEq("domain", paramDomain);
			}
			if (paramEnable != null && paramEnable.length == 1) {
				cri.addEq("enable", Boolean.parseBoolean(paramEnable[0]));
			}
			
			int entitySize = creditcardService.getListSize(cri).intValue();
			getPager().setTotalSize(entitySize);
			campaignList = creditcardService.getList(getPager().getCurrentPage() * getPager().getPageRecord(), getPager().getPageRecord(), cri, new String[]{"startDate", "campaignName asc", "id"});
		} catch (Exception e) {
			addActionError("搜寻失败：" + e.getMessage());
			e.printStackTrace();
		}
		return "list";
	}
	
	public String add() {
		initVariables();
		creditcardId = "";
		
		Calendar cal = DateUtil.getToday();
		cal.add(Calendar.DATE, 7);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		creditcard.setStartDate(cal.getTime());
		
		cal.add(Calendar.MONTH, 1);
		creditcard.setEndDate(DateUtil.getLastTimestamp(Calendar.DATE, cal.getTime()));
		
		menuSetting = creditcardSettingService.getCreditcardSettingMap();
		
		return "edit";
	}
	
	public String addDetail() {
		if(creditcard == null) {
			addActionError("信用卡活动不存在, 重新选取");
			return search();
		}
		
		if( StringUtils.isBlank(bankId) ) {
			addFieldError("bankId", "請選擇要设定的银行及卡别");
			return "edit";
		}
		
		// To note bankId(creditcard_setting_id) which user has chosen
		if( StringUtils.isBlank(bankIdNote) ) {
			bankIdNote = bankId;
		} else {
			boolean isExist = false;
			for(String noteId : bankIdNote.split(",")) {
				if(bankId.equals(noteId)) {
					isExist = true;
					break;
				}
			}
			
			if(isExist) {
				addFieldError("detailId", "此银行及卡别已經设定");
				return "edit";
			} else {
				bankIdNote += "," + bankId;
			}
		}
		
		// get fresh creditcard_setting data
		menuSetting = creditcardSettingService.getCreditcardSettingMap();
		
		// Clone creditcard setting
		if(showDetails == null || showDetails.size() == 0) {
			showDetails = new ArrayList<CardDetail>();
		}
		
		CardDetail newDetail = new CardDetail();
		newDetail.clone(menuSetting.get(bankId));
		showDetails.add(newDetail);
		
		return "edit";
	}
	
	public String delDetail() {
		if(creditcard == null) {
			addActionError("信用卡活动不存在, 重新选取");
			return search();
		}
		
		if(showDetails != null && showDetails.size() > 0) {
			CardDetail tmp = showDetails.get(operation);
			
			String[] tmpIds = bankIdNote.split(",");
			String tmpNote = "";
			for(String tmpId : tmpIds) {
				if( !tmpId.equals(tmp.getBankId()) ) {
					if("".equals(tmpNote))
						tmpNote += tmpId;
					else 
						tmpNote += ("," + tmpId);
				}
			}
			bankIdNote = tmpNote;
			
			long cdId = showDetails.get(operation).getId();
			if(cdId != 0) {
				int hitNo = 0;
				for( int i = 0; i < cardDetails.size(); i++ ) {
					if( cdId == cardDetails.get(i).getId() ) {
						hitNo = i;
						cardDetails.get(i).setDelete(true);
						break;
					}
				}
				//if(hitNo != 0) 
					//cardDetails.remove(hitNo);
			}
			showDetails.remove(operation);
		}
		
		return "edit";
	}
	
	public String edit() {
		initVariables();
		
		if( !StringUtils.isBlank(creditcardId) ) {
			menuSetting = creditcardSettingService.getCreditcardSettingMap();
			
			creditcard = creditcardService.get(new Long(creditcardId).longValue());
			//cardDetails =  creditcard.getCardDetails();
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("creditcard", creditcard);
			cardDetails =  creditcardDetailService.getList(0, -1, criteria, new String[] {});
			
			showDetails = new ArrayList<CardDetail>();
			for(CreditcardDetail cd : cardDetails) {
				CardDetail d = new CardDetail();
				d.clone(cd);
				showDetails.add(d);
				
				if( StringUtils.isBlank(bankIdNote) ) {
					bankIdNote += cd.getSetting().getId();
				} else {
					bankIdNote += ("," + cd.getSetting().getId());
				}
			}
			
			if( StringUtils.isBlank(creditcard.getCookie()) )
				ignoreCookie = true;
			else 
				ignoreCookie = false;
		} else {
			addActionError("信用卡活动不存在, 重新选取");
			return search();
		}
		
		return "edit";
	}
	
	public String save() {
		try {
			if(creditcard == null) {
				addActionError("信用卡活动不存在, 重新选取");
				return search();
			}
			
			if( !StringUtils.isBlank(creditcardId) ) {
				long currentId = new Long(creditcardId).longValue();
				if( creditcard.getId() != currentId ) {
					addActionError("资料异动错误, 回覆原始资料, 请勿同时操作两视窗");
					creditcard = creditcardService.get(currentId);
					return "edit";
				}
			}
			
			if(creditcardCampaignValidate()) {
				int no = 1;
				for(CardDetail cardDetail : showDetails) {
					CreditcardDetail sd = new CreditcardDetail();
					sd.setId(cardDetail.getId());
					sd.setSetting(creditcardSettingService.get(new Long(cardDetail.getBankId()).longValue()));
					
					List<String> periodList = new ArrayList<String>();
					Map<String, JSONArray> map = new HashMap<String, JSONArray>();
					for(int i = 0; i < cardDetail.getPeriods().size(); i++) {
						String period = cardDetail.getPeriods().get(i);
						if( !StringUtils.isBlank(period) ) {
							periodList.add(period);
							List<String> dl = new ArrayList<String>();
							
							String fee = cardDetail.getFees().get(i);
							dl.add(fee);
							
							String downLimit = cardDetail.getDownLimits().get(i);
							dl.add(downLimit);
							
							String upLimit = cardDetail.getUpLimits().get(i);
							dl.add(upLimit);
							JSONArray ja = new JSONArray(dl);
							
							map.put(period, ja);
						}
					}
					JSONArray ja = new JSONArray(periodList);
					sd.setCreditcardPeriod(ja.toString());
					
					JSONObject jo = new JSONObject(map);
					sd.setCreditcardDetail(jo.toString());
					
					if( StringUtils.isNotBlank(creditcardId) ) {
						boolean isExist = false;
						for(int i = 0; i < cardDetails.size(); i++) {
							long cdId = new Long(cardDetail.getId()).intValue();
							CreditcardDetail target = cardDetails.get(i);
							if( cdId == target.getId() ) {
								isExist = true;
								target.setCreditcardPeriod(sd.getCreditcardPeriod());
								target.setCreditcardDetail(sd.getCreditcardDetail());
								break;
							}
						}
						if(!isExist)
							cardDetails.add(sd);
					} else 
						cardDetails.add(sd);
				}
				
				creditcard.setStartDate(DateUtil.convertStringToDate(EcConstant.PATTERN_TIMESTAMP_HH_MM, startDate + " " + startTime));
				creditcard.setEndDate(DateUtil.convertStringToDate(EcConstant.PATTERN_TIMESTAMP_HH_MM, endDate + " " + endTime));
				
				boolean isSave = true;
				try {
					if( StringUtils.isBlank(creditcardId) )
						isSave = creditcardService.saveCreditcardCombine(creditcard, cardDetails);
					else 
						isSave = creditcardService.updateCreditcardCombine(creditcard, cardDetails);
				} catch (Exception e) {
					e.printStackTrace();
					addActionError("储存失败：" + e.getMessage());
					isSave = false;
				}
				//isSave = false;
				if( isSave ) { 
					creditcardId = creditcard.getId() + "";
					addActionMessage("储存成功");
					return edit();
				} else {
					return "edit";
				}
			}
		} catch (Exception e) {
			addActionError("储存失败：" + e.getMessage());
			e.printStackTrace();
			return "edit";
		}
		return "edit";
	}
	
	public String delete() {
		try {
			if( StringUtils.isBlank(creditcardId) ) {
				addActionError("信用卡活动不存在");
				return search();
			}
			
			creditcardService.delete(creditcardService.get(new Long(creditcardId).longValue()));
		} catch (Exception e) {
			addActionError("删除失败：" + e.getMessage());
			e.printStackTrace();
		}
		return search();
	}
	
	void initVariables() {
		creditcard = new Creditcard();
		cardDetails = new ArrayList<CreditcardDetail>();
		
		showDetails = new ArrayList<CardDetail>();
		
		bankId = "";
		bankIdNote = "";
		startDate = "";
		endDate = "";
		startTime = "";
		endTime = "";
	}
	
	private boolean creditcardCampaignValidate() {
		
		if( StringUtils.isBlank(creditcard.getCampaignName()) ) {
			addFieldError("creditcard_campaignName", "请输入活动名称");
		}
		
		if( StringUtils.isBlank(creditcard.getCampaignDesc()) ) {
			addFieldError("creditcard_campaignDesc", "请输入活动说明");
		}
		
		if( StringUtils.isBlank(creditcard.getCampaignDetail()) ) {
			addFieldError("creditcard_campaignDetail", "请输入活动规则");
		}
		
		if( !Range.Order.equals(creditcard.getRange()) && creditcard.getCampaignRangeDet().length() == 0 && creditcard.isEnable() ) {
			addFieldError("creditcard_range", "信用卡活动" + creditcard.getRange().getDesc() + "區間未設定");
		}
		
		if( !StringUtils.isBlank(creditcard.getCampaignRangeDet()) ) {
			if( Range.Category.equals(creditcard.getRange()) ) {
				String[] idArray = StringUtils.split(creditcard.getCampaignRangeDet(), ",");
				for (String id : idArray) {
					id = StringUtils.remove(id, System.getProperty("line.separator"));
					Category c = categoryService.get(Long.valueOf(StringUtils.trim(id)));
					if (c == null) {
						addFieldError("creditcard_campaignRangeDet", "活动分類" + id + "不存在");
					}
				}
			} else if( Range.Product.equals(creditcard.getRange()) ) {
				String[] idArray = StringUtils.split(creditcard.getCampaignRangeDet(), ",");
				for (String id : idArray) {
					Product p = productService.get(id);
					if (p == null) {
						addFieldError("creditcard_campaignRangeDet", "活动商品" + id + "不存在");
					}
				}
			}
		}
		
		if (ignoreCookie) {
			creditcard.setCookie(null);
		} else if(creditcard.getCookieArray().size() == 0) {
			addFieldError("creditcard_cookieArray", "特定渠道活動需指定一個以上渠道");
		}
		
		if( StringUtils.isBlank(creditcard.getMemo()) ) {
			addFieldError("creditcard_memo", "请输入备注");
		}
		
		if(showDetails == null || showDetails.size() == 0) {
			addFieldError("creditcard_cardDetails", "至少要设定一家银行及卡别");
		} else {
			for(int i = 0; i < showDetails.size(); i++) {
				CardDetail cardDetail = showDetails.get(i);
				
				CreditcardSetting cs = creditcardSettingService.get(new Long(cardDetail.getBankId()).longValue());
				
				if(cs == null) {
					addFieldError("creditcard_cardDetails" + i, cardDetail.getBankName() + "银行及卡别设定不存在");
				} else {
					boolean isPeriodBlank = true;
					for(int j = 0; j < cardDetail.getPeriods().size(); j++) {
						if( !StringUtils.isBlank(cardDetail.getPeriods().get(j)) ) {
							isPeriodBlank = false;
							if( StringUtils.isBlank(cardDetail.getFees().get(j)) ) {
								addFieldError("fees_" + i + "" + j, "请输入" + cardDetail.getBankName() + "-" + cardDetail.getPeriods().get(j) + "期的会员自付手续费");
							}
							
							if( StringUtils.isBlank(cardDetail.getDownLimits().get(j)) ) {
								addFieldError("downLimits_" + i + "" + j, "请输入" + cardDetail.getBankName() + "-" + cardDetail.getPeriods().get(j) + "期的交易金额下限");
							}
							
							if( StringUtils.isBlank(cardDetail.getUpLimits().get(j)) ) {
								addFieldError("upLimits_" + i + "" + j, "请输入" + cardDetail.getBankName() + "-" + cardDetail.getPeriods().get(j) + "期的交易金额上限");
							}
							
							if( !StringUtils.isBlank(cardDetail.getDownLimits().get(j)) && !StringUtils.isBlank(cardDetail.getUpLimits().get(j)) ) {
								if( NumberUtils.toFloat(cardDetail.getDownLimits().get(j)) > NumberUtils.toFloat(cardDetail.getUpLimits().get(j)) ) {
									addFieldError("detail", cardDetail.getBankName() + "-" + cardDetail.getPeriods().get(j) + "期的交易下限金额要小于上限金额");
								}
							}
						}
					}
					
					if(isPeriodBlank) {
						addFieldError("creditcard_cardDetails" + i, "请选择" + cardDetail.getBankName() + "信用卡支持期数");
					}
				}
			}
		}
		
		if (getFieldErrors().isEmpty()) {
			return true;
		} else {
			return false;
		}
	}
	
	@Override
	public void prepare() throws Exception {
		super.prepare();
		
		if (menuChannel == null) {
			menuChannel = menuService.get("Channel.Name").clone();
			menuChannel.addOption("yaodian100", "耀点100");
		}
		
		if (menuDomain == null) {
			menuDomain = menuService.get("Site.domain");
		}
		
		//if(menuSetting == null) {
			//menuSetting = creditcardSettingService.getCreditcardSettingMap();
		//}
	}
	
	// Getters & Setters
	public DomainService<Menu> getMenuService() {
		return menuService;
	}

	public CreditcardService getCreditcardService() {
		return creditcardService;
	}

	public CreditcardSettingService getCreditcardSettingService() {
		return creditcardSettingService;
	}

	public void setCreditcardSettingService(
			CreditcardSettingService creditcardSettingService) {
		this.creditcardSettingService = creditcardSettingService;
	}

	public void setCreditcardService(CreditcardService creditcardService) {
		this.creditcardService = creditcardService;
	}

	public void setMenuService(DomainService<Menu> menuService) {
		this.menuService = menuService;
	}

	public List<Creditcard.Range> getParamRanges() {
		return paramRanges;
	}

	public void setParamRanges(List<Creditcard.Range> paramRanges) {
		this.paramRanges = paramRanges;
	}

	public String getParamName() {
		return paramName;
	}

	public void setParamName(String paramName) {
		this.paramName = paramName;
	}

//	public String getParamStartDate() {
//		if (paramStartDate != null) {
//			return DateUtil.convertDateToString("yyyy-MM-dd", paramStartDate);
//		} else {
//			return "";
//		}
//	}

//	public void setParamStartDate(String paramStartDate) {
//		if (StringUtils.isNotBlank(paramStartDate)) {
//			if (paramStartDate.indexOf("/") != -1) {
//				this.paramStartDate = DateUtil.convertStringToDate("yyyy/MM/dd", paramStartDate);
//			} else if (paramStartDate.indexOf("-") != -1) {
//				this.paramStartDate = DateUtil.convertStringToDate("yyyy-MM-dd", paramStartDate);
//			} else {
//				this.paramStartDate = DateUtil.convertStringToDate(paramStartDate);
//			}
//		} else {
//			this.paramStartDate = null;
//		}
//	}

	public String getParamEndDate() {
		if (paramEndDate != null) {
			return DateUtil.convertDateToString("yyyy-MM-dd", paramEndDate);
		} else {
			return "";
		}
	}

	public void setParamEndDate(String paramEndDate) {
		if (StringUtils.isNotBlank(paramEndDate)) {
			if (paramEndDate.indexOf("/") != -1) {
				this.paramEndDate = DateUtil.convertStringToDate("yyyy/MM/dd", paramEndDate);
			} else if (paramEndDate.indexOf("-") != -1) {
				this.paramEndDate = DateUtil.convertStringToDate("yyyy-MM-dd", paramEndDate);
			} else {
				this.paramEndDate = DateUtil.convertStringToDate(paramEndDate);
			}
		} else {
			this.paramEndDate = null;
		}
	}

	public String getParamStartDate() {
		if (paramStartDate != null) {
			return DateUtil.convertDateToString("yyyy-MM-dd", paramStartDate);
		} else {
			return "";
		}
	}

	public void setParamStartDate(String paramStartDate) {
		if (StringUtils.isNotBlank(paramStartDate)) {
			if (paramStartDate.indexOf("/") != -1) {
				this.paramStartDate = DateUtil.convertStringToDate("yyyy/MM/dd", paramStartDate);
			} else if (paramStartDate.indexOf("-") != -1) {
				this.paramStartDate = DateUtil.convertStringToDate("yyyy-MM-dd", paramStartDate);
			} else {
				this.paramStartDate = DateUtil.convertStringToDate(paramStartDate);
			}
		} else {
			this.paramStartDate = null;
		}
	}

	public String getParamCookie() {
		return paramCookie;
	}

	public void setParamCookie(String paramCookie) {
		this.paramCookie = paramCookie;
	}

	public String getParamDomain() {
		return paramDomain;
	}

	public void setParamDomain(String paramDomain) {
		this.paramDomain = paramDomain;
	}

	public String[] getParamEnable() {
		return paramEnable;
	}

	public void setParamEnable(String[] paramEnable) {
		this.paramEnable = paramEnable;
	}

	public List<Creditcard.Range> getMenuRange() {
		return menuRange;
	}

	public void setMenuRange(List<Creditcard.Range> menuRange) {
		this.menuRange = menuRange;
	}

	public Menu getMenuDomain() {
		return menuDomain;
	}

	public void setMenuDomain(Menu menuDomain) {
		this.menuDomain = menuDomain;
	}

	public Menu getMenuChannel() {
		return menuChannel;
	}

	public void setMenuChannel(Menu menuChannel) {
		this.menuChannel = menuChannel;
	}

	public List<Creditcard> getCampaignList() {
		return campaignList;
	}

	public void setCampaignList(List<Creditcard> campaignList) {
		this.campaignList = campaignList;
	}

	public Creditcard getCreditcard() {
		return creditcard;
	}

	public void setCreditcard(Creditcard creditcard) {
		this.creditcard = creditcard;
	}

	public String getCreditcardId() {
		return creditcardId;
	}

	public void setCreditcardId(String creditcardId) {
		this.creditcardId = creditcardId;
	}

	public String getStartDate() {
		return startDate;
	}

	public void setStartDate(String startDate) {
		this.startDate = startDate;
	}

	public String getStartTime() {
		return startTime;
	}

	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}

	public String getEndDate() {
		return endDate;
	}

	public void setEndDate(String endDate) {
		this.endDate = endDate;
	}

	public String getEndTime() {
		return endTime;
	}

	public void setEndTime(String endTime) {
		this.endTime = endTime;
	}

	public boolean isIgnoreCookie() {
		return ignoreCookie;
	}

	public void setIgnoreCookie(boolean ignoreCookie) {
		this.ignoreCookie = ignoreCookie;
	}

	public Map<String, CreditcardSetting> getMenuSetting() {
		return menuSetting;
	}

	public void setMenuSetting(Map<String, CreditcardSetting> menuSetting) {
		this.menuSetting = menuSetting;
	}

	public String getBankId() {
		return bankId;
	}

	public void setBankId(String bankId) {
		this.bankId = bankId;
	}

	public String getBankIdNote() {
		return bankIdNote;
	}

	public void setBankIdNote(String bankIdNote) {
		this.bankIdNote = bankIdNote;
	}

	public int getOperation() {
		return operation;
	}

	public void setOperation(int operation) {
		this.operation = operation;
	}

	public CategoryService getCategoryService() {
		return categoryService;
	}

	public void setCategoryService(CategoryService categoryService) {
		this.categoryService = categoryService;
	}

	public ProductService getProductService() {
		return productService;
	}

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	public List<CardDetail> getShowDetails() {
		return showDetails;
	}

	public void setShowDetails(List<CardDetail> showDetails) {
		this.showDetails = showDetails;
	}

	public List<CreditcardDetail> getCardDetails() {
		return cardDetails;
	}

	public void setCardDetails(List<CreditcardDetail> cardDetails) {
		this.cardDetails = cardDetails;
	}
}
